﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.ComponentModel.Composition;
using MVVMGrid.UsingReactive.ViewModels;
using MVVMGrid.UsingReactive.Models;

namespace MVVMGrid.UsingReactive.Views
{
    [Export(typeof(UserControl))]
    public partial class GridView : UserControl
    {
        [Import]
        public GridViewModel ViewModel
        {
            get { return DataContext as GridViewModel; }
            set { DataContext = value; OnViewModelChanged(); }
        }

        public GridView()
        {
            InitializeComponent();
        }

        private IDisposable notifyChangedSubscription;

        private void OnViewModelChanged()
        {
            if( notifyChangedSubscription != null )
            {
                notifyChangedSubscription.Dispose();
                notifyChangedSubscription = null;
            }
            if( ViewModel != null )
            {
                notifyChangedSubscription =
                    Observable
                        .FromEvent<PropertyChangedEventHandler, PropertyChangedEventArgs>(
                            h => new PropertyChangedEventHandler( h ),
                            h => ViewModel.PropertyChanged += h,
                            h => ViewModel.PropertyChanged -= h )
                        .Where( evt => evt.EventArgs.PropertyName == "ViewSettings" )
                        .Subscribe( evt =>
                        {
                            UpdateColumns();
                        } );
            }
        }

        private static string GetColumnID( DataGridColumn gridColumn )
        {
            return (string)gridColumn.GetValue( FrameworkElement.NameProperty );
        }

        private void UpdateColumns()
        {
            int displayIndex = 0;
            ViewModel.ViewSettings.Columns
                .GroupJoin(
                    dataGrid.Columns,
                    vc => vc.ColumnID,
                    gc => GetColumnID( gc ),
                    ( vc, gc ) => Tuple.Create( vc, gc.FirstOrDefault() ) )
                .Concat(
                    dataGrid.Columns
                        .Where( gc => !ViewModel.ViewSettings.Columns
                                            .Where( vc => GetColumnID( gc ) == vc.ColumnID )
                                            .Any() )
                        .Select( gc => Tuple.Create( ViewColumnSettings.Null, gc ) ) )
                .ToList()
                .ForEach( t =>
                {
                    ViewColumnSettings viewCol = t.Item1;
                    DataGridColumn gridCol = t.Item2;

                    if( viewCol == null )
                        gridCol.Visibility = System.Windows.Visibility.Collapsed;
                    else
                    {
                        gridCol.Visibility = System.Windows.Visibility.Visible;
                        gridCol.Width = new DataGridLength( viewCol.ColumnWidth, DataGridLengthUnitType.Pixel );
                        gridCol.DisplayIndex = displayIndex++;
                    }
                } );
        }
    }
}
